package com.lrh.netty;


import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

// 自定义处理类
// TextWebSocketFrame  : websocket数据是以帧的形式处理的
@Component
@ChannelHandler.Sharable // 设置通道共享
public class WebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    private Logger log = LoggerFactory.getLogger(this.getClass());


    private static List<Channel> channelList = new ArrayList<>();


    // 通道就绪事件
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // 有新的客户端连接时 , 会进入该方法
        // 得到连接的通道
        Channel channel = ctx.channel();
        // 有新的客户端的连接 就放入到集合中
        channelList.add(channel);
        log.info("[Server] : {} 上线了. ",getClientName(channel));
    }

    // 通道未就绪 ,  也就是channel下线
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        // 客户端断开连接 移除该通道
        channelList.remove(channel);
        log.info("[Server] : {} 下线了. ",getClientName(channel));

    }

    // 读就绪事件
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception {
        // 客户端发送过来的消息
        String msg = textWebSocketFrame.text();
        log.info("msg =>  {}",msg);
        // 通过 上下文得到当前发送消息的通道
        Channel channel = channelHandlerContext.channel();
        for (Channel ch : channelList) {
            // 排除自身通道的消息
            if(ch != channel){
                ch.writeAndFlush(new TextWebSocketFrame(msg));
            }
        }
    }

    // 获取异常
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        // 移除channelList
        Channel channel = ctx.channel();
        channelList.remove(channel);
        log.info("[Server] : {} 异常. ",getClientName(channel));
    }

    // 获取
    public static String getClientName(Channel channel){
        return channel.remoteAddress().toString().substring(1);
    }
}
